package com.scott.java8concurrency.java7;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.atomic.LongAdder;

/**
 * 1~10或者更多任意数量 并行相加
 */
public class RecursiveAddOneToTenDemo {

    public static void main(String[] args) {

        //构造ForkJoin线程池
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        //需要累加的列表
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        //新城安全的累加结果集
        LongAdder longAdder = new LongAdder();
        //调用迭代累加任务
        forkJoinPool.invoke(new AddTask(numbers, longAdder));

        System.out.println(numbers + "累加结果为" + longAdder);

    }

    /**
     * 使用二分法进行迭代累加计算
     */
    private static class AddTask extends RecursiveAction {

        private static final long serialVersionUID = -7451462671486485356L;
        /**
         * 带累加的数据列表
         */
        private final List<Integer> numbers;

        /**
         * 累加器，线程安全的累加聚合器
         */
        private LongAdder longAdder;

        private AddTask(List<Integer> numbers, LongAdder longAdder) {
            this.numbers = numbers;
            this.longAdder = longAdder;
        }

        @Override
        protected void compute() {
            //当待累加的数量超过2的时候，则进行二分
            if (numbers.size() > 1) {
                int offsite = numbers.size() / 2;
                System.out.println(Thread.currentThread().getName());
                List<Integer> leftPart = numbers.subList(0, offsite);
                List<Integer> rightPart = numbers.subList(offsite, numbers.size());
                invokeAll(new AddTask(leftPart, longAdder), new AddTask(rightPart, longAdder));
            } else {
                if (numbers.size() == 1) { //保护操作
                    //如果只有一个，则直接累加
                    longAdder.add(numbers.get(0));
                }
            }

        }
    }
}
